extends Enemy

enum State {
	IDLE,
	WALK,
	RUN,
	HURT,
	DYING,
}

const KNOCKBACK_AMOUNT := 512.0

var pending_damage:Damage

@onready var wall_checker:RayCast2D = $Graphics/WallChecker
@onready var player_checker:RayCast2D = $Graphics/PlayerChecker
@onready var floor_checker:RayCast2D = $Graphics/FloorChecker
@onready var cd_timer:Timer = $CDTimer


func can_see_player() -> bool:
	if not player_checker.is_colliding():
		return false
	return player_checker.get_collider() is Player


func tick_physics(state:State, delta:float):
	match state:
		State.IDLE, State.HURT, State.DYING:
			move(0.0, delta)
		State.WALK:
			move(max_speed/3, delta)
		State.RUN:
			if wall_checker.is_colliding() or not floor_checker.is_colliding():
				direction *= -1
			move(max_speed, delta)
			if can_see_player():
				cd_timer.start()


func get_next_state(state:State) -> int:
	if stats.health <= 0:
		return FSM.KEEP_CURRENT if state == State.DYING else State.DYING
	if pending_damage:
		return State.HURT
	
	match state:
		State.IDLE:
			if can_see_player():
				return State.RUN
			if fsm.state_time > 2:
				return State.WALK
		State.WALK:
			if can_see_player():
				return State.RUN
			if wall_checker.is_colliding() or not floor_checker.is_colliding():
				return State.IDLE
		State.RUN:
			if not can_see_player() and cd_timer.is_stopped():
				return State.WALK
		State.HURT:
			if not animation_player.is_playing():
				return State.RUN
	return FSM.KEEP_CURRENT


func transition_state(from:State, to:State):
	match to :
		State.IDLE:
			animation_player.play("idle")
			if wall_checker.is_colliding():
				direction *= -1
		State.WALK:
			animation_player.play("walk")
			if not floor_checker.is_colliding():
				direction *= -1
				floor_checker.force_raycast_update()
		State.RUN:
			animation_player.play("run")
		State.HURT:
			animation_player.play("hit")
			stats.health -= pending_damage.amount
			var dir := pending_damage.source.global_position.direction_to(global_position)
			velocity = dir * KNOCKBACK_AMOUNT
			direction = Direction.LEFT if dir.x > 0 else Direction.RIGHT
			pending_damage = null
		State.DYING:
			animation_player.play("die")
	pass


func _on_hurtbox_hurt(hitbox:Hitbox):
	pending_damage = Damage.new()
	pending_damage.amount = 1
	pending_damage.source = hitbox.owner
